package com.wdb.modules.quartz.utils;

import com.wdb.utils.SpringContextHolder;
import com.wdb.utils.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

/**
 * @author: wendaobai@qq.com
 * @date: 2024/8/22 星期四 9:45
 */
public class QuartzRunnable implements Callable<Object> {

  /**
   * Quartz任务执行的运行时对象
   *
   * <p>通过Spring上下文获取目标Bean，并根据是否有参数获取相应的方法对象 在方法调用时，确保方法可访问，并根据存在参数情况调用相应方法
   */
  private final Object target; // 目标对象

  private final Method method; // 需要调用的方法
  private final String params; // 方法参数

  /**
   * 构造QuartzRunnable对象
   *
   * @param beanName 要执行的Bean名称
   * @param methodName Bean中的方法名
   * @param params 方法参数，可为空
   * @throws NoSuchMethodException 如果方法不存在
   */
  public QuartzRunnable(String beanName, String methodName, String params)
      throws NoSuchMethodException {
    this.target = SpringContextHolder.getBean(beanName); // 通过Spring上下文获取Bean
    this.params = params; // 设置方法参数
    if (StringUtils.isNoneBlank(this.params)) {
      // 如果参数不为空，获取带有String类参数的方法
      this.method = target.getClass().getDeclaredMethod(methodName, String.class);
    } else {
      // 如果参数为空，获取无参数的方法
      this.method = target.getClass().getDeclaredMethod(methodName);
    }
  }

  /**
   * 执行任务
   *
   * <p>调用目标对象的方法，根据参数情况决定调用方式 确保方法在调用前是可访问的
   *
   * @return 任务执行结果，此处总是返回null
   * @throws Exception 如果方法调用失败
   */
  @Override
  public Object call() throws Exception {
    ReflectionUtils.makeAccessible(this.method); // 确保方法可访问
    if (StringUtils.isNoneBlank(this.params)) {
      // 如果参数不为空，调用带有参数的方法
      this.method.invoke(target, this.params);
    } else {
      // 如果参数为空，调用无参数的方法
      this.method.invoke(target);
    }
    return null; // 返回null，表示任务执行完成
  }
}
